﻿using Capture.Utils;
using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Capture
{

    public class MongoHelp : IDisposable
    {
        private MongoClient _serve = null;
        private String _dbConnect = Config.MongdbCon;
        private String _dbName = Config.MDatabase;
        private String _dbTable = "DataCapture";
        //TWY.MongDBase
        //返回MongDB连接服务;
        private MongoClient Serve { get { return _serve != null ? _serve : new MongoClient(Connect + @"/" + DB); } }//本地

        public MongoHelp() { }

        public MongoHelp(String connect = null, String dbbase = null, String table = null)
        {
            Connect = String.IsNullOrEmpty(connect) ? _dbConnect : connect;
            DB = String.IsNullOrEmpty(dbbase) ? _dbName : dbbase;
            Table = String.IsNullOrEmpty(table) ? _dbTable : table;
        }

        /// <summary>
        /// 获取或设置连接语句
        /// </summary>
        public String Connect
        {
            get { return _dbConnect; }
            set { _dbConnect = value; }
        }

        /// <summary>
        /// 库名获取或设置;
        /// </summary>
        public String DB
        {
            get { return _dbName; }
            set { _dbName = value; }
        }

        /// <summary>
        /// 表名获取或设置
        /// </summary>
        public String Table
        {
            get { return _dbTable; }
            set { _dbTable = value; }
        }

        /// <summary>
        /// 获取行数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public long GetRowCount<T>()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            return table.Count(new BsonDocument());
        }


        /// <summary>
        /// 插入单条数据;
        /// </summary>
        public void Insert<T>(T c) where T : new()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            table.InsertOne(c);
        }

        /// <summary>
        /// 插入单条数据;
        /// </summary>
        public async Task InsertAsync<T>(T c) where T : new()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            await table.InsertOneAsync(c);
        }

        /// <summary>
        /// 插入多条数据;
        /// </summary>
        public void Inserts<T>(IEnumerable<T> list) where T : new()
        {
            if (list.Count() < 1)
                return;
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            table.InsertMany(list);
        }

        /// <summary>
        /// 插入多条数据;
        /// </summary>
        public async Task InsertsAsync<T>(IEnumerable<T> list,InsertManyOptions options) where T : new()
        {
            if (list.Count() < 1)
                return;
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            await table.InsertManyAsync(list, options);
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        public void Update<T>(FilterDefinition<T> filter, UpdateDefinition<T> update) where T : new()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            //var _filter = Builders<T>.Filter.Eq("", "");//条件;
            //var _update = Builders<T>.Update.Set("", "");
            table.UpdateMany(filter, update);
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        public async Task UpdateAsync<T>(T c, FilterDefinition<T> filter, UpdateDefinition<T> update) where T : new()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            await table.UpdateOneAsync(filter, update);
        }

        /// <summary>
        /// 删除数据
        /// </summary>
        public void Delete<T>(FilterDefinition<T> filter) where T : new()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            table.DeleteMany(filter);
        }

        /// <summary>
        /// 获取库中所有表名
        /// </summary>
        public IList<String> GetTableNames()
        {
            IList<String> _result = new List<String>();
            var db = Serve.GetDatabase(_dbName);
            foreach (var i in db.ListCollections().ToList())
                _result.Add(i[0].ToString());
            return _result;
        }

        /// <summary>
        /// 获取单表的一条数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="filter"></param>
        /// <returns></returns>
        public T GetOne<T>(FilterDefinition<T> filter) where T : class,new()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            return table.Find(filter).FirstOrDefault() ?? new T();
        }

        /// <summary>
        /// 获取单表的多条数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="filter"></param>
        /// <returns></returns>
        public List<T> GetMany<T>(FilterDefinition<T> filter) where T : class,new()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            return table.Find(filter).ToList();
        }

        /// <summary>
        /// 获取符合条件的记录条数
        /// </summary>
        public long GetCount<T>(FilterDefinition<T> where,string table = null) where T : class 
        {
            var db = Serve.GetDatabase(_dbName);
            table = table ?? _dbTable;
            return db.GetCollection<T>(table).Count(where);
        }

        /// <summary>
        /// 获取指定条数;
        /// </summary>
        public List<T> Sreach<T>(int nowPage, int pageSize, FilterDefinition<T> where, out long totalCount) where T : new()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            var _totalCount = table.Count(where);
            totalCount = _totalCount;
            if (_totalCount == 0)
                return new List<T>(0);

            totalCount = _totalCount;
            var _sort = Builders<T>.Sort.Descending("CreateTime");
            var _project = Builders<T>.Projection.Exclude("_id");
            return table.Find<T>(where).Project<T>(_project).Sort(_sort).Skip(nowPage * pageSize).Limit(pageSize).ToList();
        }

        /// <summary>
        /// 获取指定条数(含_id);
        /// </summary>
        public List<T> Sreach<T>(int nowPage, int pageSize, out int totalCount,FilterDefinition<T> where = null) where T : new()
        {
            where = where ?? new BsonDocument();
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            var _totalCount = table.Count(where);
            totalCount = Convert.ToInt32(_totalCount);
            if (_totalCount == 0)
                return new List<T>(0);
            var _sort = Builders<T>.Sort.Descending("CreateTime");
            //var _project = Builders<T>.Projection.Exclude("_id");
            where = where == null ? new BsonDocument() : where;
            return table.Find<T>(where).Sort(_sort).Skip(nowPage * pageSize).Limit(pageSize).ToList();
        }

        /// <summary>
        /// 获取指定条数;
        /// </summary>
        public IEnumerable<T> Sreach<T>(int nowPage, int pageSize) where T : new()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            var _sort = Builders<T>.Sort.Descending("CreateTime");
            //var _project = Builders<T>.Projection.Exclude("_id");
            //return table.Find<T>(new BsonDocument()).Project<T>(_project).Sort(_sort).Skip(nowPage * pageSize).Limit(pageSize).ToList();
            return table.Find<T>(new BsonDocument()).Sort(_sort).Skip(nowPage * pageSize).Limit(pageSize).ToList();
        }


        /// <summary>
        /// 搜索指定时间段的数据;
        /// </summary>
        public IEnumerable<T> Sreach<T>(DateTime start, DateTime end) where T : new()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            var _filter = Builders<T>.Filter.Gte<DateTime>("CreateTime", start) & Builders<T>.Filter.Lt<DateTime>("CreateTime", end);
            var _sort = Builders<T>.Sort.Descending("CreateTime");
            var _project = Builders<T>.Projection.Exclude("_id");
            return table.Find<T>(_filter).Project<T>(_project).Sort(_sort).ToList();
        }

        /// <summary>
        /// 获取指定条数;
        /// </summary>
        public IEnumerable<T> Sreach<T>(int nowPage, int pageSize, DateTime start, DateTime end) where T : new()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            var _filter = Builders<T>.Filter.Gte<DateTime>("CreateTime", start) & Builders<T>.Filter.Lt<DateTime>("CreateTime", end);
            var _sort = Builders<T>.Sort.Descending("CreateTime");
            var _project = Builders<T>.Projection.Exclude("_id");
            return table.Find<T>(_filter).Project<T>(_project).Sort(_sort).Skip(nowPage * pageSize).Limit(pageSize).ToList();
        }

        /// <summary>
        /// 跟踪搜索指定时间内的数据(IP/Session)
        /// </summary>
        public IEnumerable<T> SreachTrack<T>(DateTime start, DateTime end, String sid = null, String ip = null) where T : new()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            var _filter = Builders<T>.Filter.Gte<DateTime>("CreateTime", start) & Builders<T>.Filter.Lt<DateTime>("CreateTime", end);
            if (sid != null)
                _filter = _filter & Builders<T>.Filter.Eq<String>("SessionID", sid);
            if (ip != null)
                _filter = _filter & Builders<T>.Filter.Eq<String>("IP", ip);
            var _sort = Builders<T>.Sort.Descending("CreateTime");
            var _project = Builders<T>.Projection.Exclude("_id");
            return table.Find<T>(_filter).Project<T>(_project).Sort(_sort).ToList();
        }

        /// <summary>
        /// 搜索指定时间段的数据;
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        public IEnumerable<T> SreachGroup<T>(DateTime start, DateTime end) where T : new()
        {
            var db = Serve.GetDatabase(_dbName);
            var table = db.GetCollection<T>(_dbTable);
            var _filter = Builders<T>.Filter.Gte<DateTime>("CreateTime", start) & Builders<T>.Filter.Lt<DateTime>("CreateTime", end);
            var _project = Builders<T>.Projection.Exclude("_id");
            var _sort = Builders<T>.Sort.Descending("CreateTime");
            table.Find<T>(_filter).Project(_project).Sort(_sort).ToList();

            // var map = BsonJavaScript.Create(@"function(){emit(this.WebID, this.PV, this.UV, this.IP, this.Old, this.CreateTime);};");
            // var redunce = BsonJavaScript.Create(@"function(key, values){emit(this.cusid, this.price);};");
            //var r = table.MapReduce<Client>(map, redunce);
            //table.Aggregate(AggregateOptions.);
            return null;

        }

        public void Dispose()
        {
            //
        }
    }
}
